/*
 * adc.c
 *
 *  Created on: 2017年5月4日
 *      Author: chenss
 */


#include "io/adc.h"

#define ADC_TIMES 1

// 外部分压电阻值（千欧）
#define Rout 100

// 内部分压电阻值（千欧）
#define Rin 12

// ADC满量程值
#define ADC_MAX ((1 << 12) - 1)

// ADC参考电压（伏）
#define V_REF 3.3

// 输入端上的二极管的正向压降
#define V_DROP 0

//static const uint32_t _channels[] =
//{
//        ADC_Channel_4,
//        ADC_Channel_5,
//};

void Adc_Init(void)
{
    ADC_InitTypeDef     ADC_InitStructure;
    GPIO_InitTypeDef    GPIO_InitStructure;

    /* GPIOC Periph clock enable */
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);

    /* ADC1 Periph clock enable */
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);

    /* Configure ADC Channel11 as analog input */
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    /* ADCs DeInit */
    ADC_DeInit(ADC1);

    /* Initialize ADC structure */
    ADC_StructInit(&ADC_InitStructure);

    /* Configure the ADC1 in continuous mode with a resolution equal to 12 bits  */
    ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;
    ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;
    ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;
    ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
    ADC_InitStructure.ADC_ScanDirection = ADC_ScanDirection_Upward;
    ADC_Init(ADC1, &ADC_InitStructure);

    /* Convert the ADC1 Channel 11 with 239.5 Cycles as sampling time */
    ADC_ChannelConfig(ADC1, ADC_Channel_5 , ADC_SampleTime_55_5Cycles);

    /* ADC Calibration */
    ADC_GetCalibrationFactor(ADC1);

    /* Enable the ADC peripheral */
    ADC_Cmd(ADC1, ENABLE);

    /* Wait the ADRDY flag */
    while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_ADRDY));
}

/**
 *
 * @return 电池电压（mV）
 */
int Adc_GetVbat(void)
{
    int i, adc;
    float vRin, vVcc;
    int vbat;

//    if(adc > Adc_Max)
//    {
//        return 0;
//    }

//    ADC_ChannelConfig(ADC1, _channels[adc] , ADC_SampleTime_13_5Cycles);

    /* ADC Calibration */
//    ADC_GetCalibrationFactor(ADC1);

    /* Enable the ADC peripheral */
    ADC_Cmd(ADC1, ENABLE);

    adc = 0;
    for(i = 0; i < ADC_TIMES; i++)
    {
        /* ADC1 regular Software Start Conv */
        ADC_StartOfConversion(ADC1);

        /* Test EOC flag */
        while(ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET);

        adc += ADC_GetConversionValue(ADC1);
    }

    adc /= ADC_TIMES;

    ADC_Cmd(ADC1, DISABLE);

    vRin = (V_REF * adc)/ ((float) ADC_MAX);
    vVcc = vRin * (Rout + Rin) / Rin;
    vbat = (int) ((vVcc + V_DROP) * 1000);

    return vbat;
}
